﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using ParserGenerator.GrammarConstruction;

namespace ParserGenerator.ParserConstruction
{
    [Serializable]
    public sealed class ParserAutomatonItemLookaheadSets : ReadOnlyDictionary<ParserAutomatonItem, ParserAutomatonItemLookaheadSet>
    {
        public ParserAutomatonState State { get; internal set; }

        internal ParserAutomatonItemLookaheadSets(ParserAutomatonState state)
            : this()
        {
            if (state == null)
                throw new ArgumentNullException(nameof(state));
            State = state;
        }

        internal ParserAutomatonItemLookaheadSets()
            : base(new Dictionary<ParserAutomatonItem, ParserAutomatonItemLookaheadSet>())
        {
        }

        internal void Add(ParserAutomatonItem item, ParserAutomatonItemLookaheadSet set)
        {
            if (item == null)
                throw new ArgumentNullException(nameof(item));
            if (set == null)
                throw new ArgumentNullException(nameof(set));
            Dictionary.Add(item, set);
        }

        internal void AddValueItem(ParserAutomatonItem item, GrammarTerminalSymbol token, ParserAutomatonState state)
        {
            if (item == null)
                throw new ArgumentNullException(nameof(item));
            if (token == null)
                throw new ArgumentNullException(nameof(token));
            if (state == null)
                throw new ArgumentNullException(nameof(state));
            ParserAutomatonItemLookaheadSet set;
            if (!Dictionary.TryGetValue(item, out set))
            {
                set = new ParserAutomatonItemLookaheadSet(state, item);
                Dictionary.Add(item, set);
            }
            set.Add(token);
        }

        internal bool CheckHaveLookheads()
        {
            foreach (ParserAutomatonItemLookaheadSet set in Dictionary.Values)
                if (set.Count > 0)
                    return true;
            return false;
        }

        internal HashSet<GrammarTerminalSymbol> GetAllTokens()
        {
            HashSet<GrammarTerminalSymbol> tokens = new HashSet<GrammarTerminalSymbol>();
            foreach (ParserAutomatonItemLookaheadSet set in Dictionary.Values)
                tokens.UnionWith(set);
            return tokens;
        }
    }
}
